package com.service.admin.otc.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.service.admin.otc.controller.rep.OtcTradeDetailRep;
import com.service.admin.otc.controller.req.OtcOrderPageReq;
import com.service.admin.support.RedisLockConstant;
import com.service.core.exception.CommonException;
import com.service.core.rest.response.CommonPageRep;
import com.service.dao.po.OtcOrderPO;
import com.service.dao.query.OtcQueryParams;
import com.service.dao.enums.MemberJAType;
import com.service.dao.enums.OtcStatusEnum;
import com.service.dao.enums.OtcTypeEnum;
import com.service.dao.mapper.OtcOrderMapper;
import com.service.dao.model.*;
import com.service.admin.member.service.MemberJAService;
import com.service.admin.member.service.MemberService;
import com.service.admin.otc.controller.rep.OtcOrderPageRep;
import com.service.admin.member.service.MemberStoreService;
import com.service.admin.otc.service.OtcOrderDetailService;
import com.service.admin.otc.service.OtcOrderService;
import com.service.admin.support.MemberStoreLockUtils;
import com.service.utility.modelmapper.ModelMapperUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;


@Service("hmOtcOrderService")
@Slf4j
public class OtcOrderServiceImpl extends ServiceImpl<OtcOrderMapper, OtcOrder> implements OtcOrderService {

    @Autowired
    private MemberService memberService;
    @Autowired
    private MemberJAService memberJAService;
    @Autowired
    private MemberStoreService memberStoreService;

    @Autowired
    private OtcOrderDetailService otcOrderDetailService;

    @Autowired
    private MemberStoreLockUtils storeLockUtils;
    /**
     * 获取账户
     *
     * @param memberId
     * @param coinTypeId
     * @return
     */
    private MemberStore getMemberStore(Integer memberId, Integer coinTypeId) {
        MemberStore memberStore = memberStoreService.getOne(new QueryWrapper<MemberStore>().lambda()
                .eq(MemberStore::getMemberId, memberId)
                .eq(MemberStore::getCoinsId, coinTypeId));
        return memberStore;
    }


    @Override
    public CommonPageRep<OtcOrderPageRep> pageOrder(OtcOrderPageReq pageRequest) {
        Page<OtcOrderPO> page = PageHelper.startPage(pageRequest.getPageNo(), pageRequest.getPageSize());
        OtcQueryParams queryParams = ModelMapperUtil.getStrictModelMapper().map(pageRequest, OtcQueryParams.class);
        baseMapper.selectByMemberAccountAndOtcType(queryParams);
        List<OtcOrderPageRep> list = page.stream().map(item -> ModelMapperUtil.getStrictModelMapper().map(item, OtcOrderPageRep.class)).collect(Collectors.toList());
        return CommonPageRep.buildResultRep(page, list);
    }

    @Override
    public List<OtcTradeDetailRep> getOtcOrderTradeDetail(Integer otcId) {
        OtcOrder otcOrder = getById(otcId);
        if (ObjectUtils.isEmpty(otcOrder)) {
            log.error("OTC交易<id:{}>无效", otcId);
            throw new CommonException("无此OTC交易订单");
        }
        return otcOrderDetailService.list(new QueryWrapper<OtcOrderDetail>().lambda()
                .eq(OtcOrderDetail::getOtcOrderId, otcId)).stream().map(item -> {
            OtcTradeDetailRep detailRep = ModelMapperUtil.getStrictModelMapper().map(item, OtcTradeDetailRep.class);
            Member member = memberService.getById(item.getMemberId());
            detailRep.setMemberAccount(member.getUserAccount());
            detailRep.setMemberName(member.getUserName());
            return detailRep;
        }).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void cancelOrder(Integer orderId) {

        OtcOrder order = getById(orderId);
        if (order.getOtcStatus() == OtcStatusEnum.CANCEL.getStatus() || order.getOtcStatus() == OtcStatusEnum.COMPLETE.getStatus()) {
            log.error("OTC订单<otcId:{}>取消失败,已完成或已取消", orderId);
            throw new CommonException("该订单已完成或已取消");
        }

        order.setOtcStatus(OtcStatusEnum.CANCEL.getStatus());
        updateById(order);
        Integer coinTypeId = order.getCoinsId();
        BigDecimal frostNum = order.getOtcResidueNum();
        if (order.getOtcType() == OtcTypeEnum.BUY.getType()) {
            coinTypeId = order.getTradeCoinsId();
            frostNum = order.getOtcResidueNum().multiply(order.getOtcPrice());
        }
        processStoreNum(order.getMemberId(), coinTypeId, frostNum, MemberJAType.OTC_TRADE_CANCEL, orderId, null);

    }

    @Transactional
    public void processStoreNum(Integer memberId, Integer coinTypeId, BigDecimal tradeAmount, MemberJAType jaType,
                                Integer orderId, Integer orderDetailId) {
        MemberStore memberStore = getMemberStore(memberId, coinTypeId);
        jaType.doOptStore(memberStore, tradeAmount);
        memberStoreService.updateById(memberStore);
        addJournalAccount(memberStore, tradeAmount, orderId, orderDetailId, jaType);
    }

    /**
     * 创建流水
     */
    @Transactional
    public void addJournalAccount(MemberStore memberStore, BigDecimal tradeAmount, Integer orderId, Integer orderDetailId,
                                  MemberJAType jaType) {
        JournalAccount journalAccount = JournalAccount.builder()
                .memberId(memberStore.getMemberId())
                .storeId(memberStore.getId())
                .jaNum(tradeAmount)
                .jaType(jaType.getCode())
                .storeNum(memberStore.getNum())
                .storeFrostNum(memberStore.getFrostNum())
                .coinsId(memberStore.getCoinsId())
                .coinsName(memberStore.getCoinsName())
                .orderId(orderId)
                .orderDetailId(orderDetailId)
                .jaRemark(jaType.getMsg())
                .build();

        memberJAService.save(journalAccount);
    }
}
